import { Inject, Provide } from '@midwayjs/core';
import { Repository } from 'typeorm';
import { Gateway } from '../../entity/firmware/gateway.entity';
import { InjectEntityModel } from '@midwayjs/typeorm';
// import { Class } from '../../entity/firmware/class.entity'
import { WristbandAdv } from '@entity/firmware/wristband_adv.entity';
import { ClassEntity } from '@entity/firmware/class.entity';
import { RedisService } from '@midwayjs/redis';
interface SleepData {
  sleep_duration: number; // 总睡眠时长（分钟）
  wake_up_time: string; // 起床时间
  bed_time: string; // 入睡时间
  deep_sleep_duration: number; // 深睡时长（分钟）
  light_sleep_duration: number; // 浅睡时长（分钟）
}
function calculateSleepData(result: any[]): SleepData {
  let sleepStart: Date | null = null;
  let wakeUpTime: Date | null = null;
  let totalSleep = 0;
  let deepSleep = 0;
  let lightSleep = 0;
  let lastState = 'awake';

  result.forEach((item) => {
    const { hr, acc_x, acc_y, acc_z, hrv, time } = item;

    // 确保日期有效
    const timestamp = new Date(time);
    if (isNaN(timestamp.getTime())) {
      // console.warn(`Invalid date: ${time}`);
      return; // 跳过无效日期的记录
    }

    const movement = Math.sqrt(acc_x ** 2 + acc_y ** 2 + acc_z ** 2);

    let currentState: 'awake' | 'light_sleep' | 'deep_sleep';

    if (hr < 50 && hrv > 40 && movement < 0.05) {
      currentState = 'deep_sleep';
    } else if (hr < 60 && movement < 0.2) {
      currentState = 'light_sleep';
    } else {
      currentState = 'awake';
    }

    if (currentState !== 'awake') {
      if (!sleepStart) sleepStart = timestamp;
      totalSleep += 1; // 假设数据是按 1 分钟间隔存储的
      if (currentState === 'deep_sleep') deepSleep += 1;
      if (currentState === 'light_sleep') lightSleep += 1;
    } else {
      if (lastState !== 'awake') {
        wakeUpTime = timestamp;
      }
    }

    lastState = currentState;
  });

  return {
    sleep_duration: totalSleep,
    wake_up_time: wakeUpTime ? wakeUpTime.toISOString() : '',
    deep_sleep_duration: deepSleep,
    light_sleep_duration: lightSleep,
    bed_time: sleepStart ? sleepStart.toISOString() : ''  // 添加 bed_time
  };
}

@Provide()
export class GatewayService {
  @InjectEntityModel(Gateway)
  gatewayRepo: Repository<Gateway>;
  @InjectEntityModel(ClassEntity)
  classRepo: Repository<ClassEntity>;
  @InjectEntityModel(WristbandAdv)
  wristbandAdvRepo: Repository<WristbandAdv>
  @InjectEntityModel(WristbandAdv)
  wristbandAdvModel: Repository<WristbandAdv>;
  @Inject()
  redisService: RedisService; // 注入 Redis 服务
  // **创建网关**
  async createGateway(data: Partial<Gateway>) {
    const gateway = this.gatewayRepo.create(data);
    return await this.gatewayRepo.save(gateway);
  }

  // **获取所有网关**
  async getAllGateways(params) {
    const { mac, class_id, version, pageSize, pageNum } = params
    console.log('班级', class_id)
    const query = this.gatewayRepo.createQueryBuilder('gateway')
      .leftJoinAndSelect('gateway.class', 'class') // 关联 class
      .leftJoinAndSelect('class.school', 'school')
    // .where('edgroup.deleted != :deleted', { deleted: true });
    if (mac) query.andWhere('gateway.mac LIKE :mac', { mac: `%${mac}%` });
    if (version) query.andWhere('gateway.version_bin LIKE :version', { version: `%${version}%` });
    if (class_id) query.andWhere('class.id LIKE :class_id', { class_id: `%${class_id}%` });
    console.log('班级1', class_id)
    if (pageSize && pageNum) {
      query.skip((pageNum - 1) * pageSize).take(pageSize);
    }
    // 按时间降序排列
    query.orderBy('gateway.time', 'DESC');
    // 查询总数 count
    const total = await query.getCount();
    // return await this.gatewayRepo.find({ relations: ['class'] }); // 加载关联的班级
    // 返回数据
    return {
      total,
      data: await query.getMany(),
    };
  }

  // 获取近5分钟活跃的网关（且未被分配到其他班级）
  async getLastGateways(params) {
    const { pageSize, pageNum, class_id } = params; // 新增 class_id 参数
    const query = this.gatewayRepo.createQueryBuilder('gateway')
      .leftJoinAndSelect('gateway.class', 'class') // 关联 class
      .leftJoinAndSelect('class.school', 'school');

    // 条件1：网关最近5分钟活跃
    const fiveMinutesAgo = new Date(Date.now() - 5 * 60 * 1000);
    query.andWhere('gateway.last_report_time >= :fiveMinutesAgo', { fiveMinutesAgo });

    // 条件2：如果传入了 class_id，则只返回未分配或已分配到该班级的网关
    if (class_id) {
      query.andWhere('(gateway.class IS NULL OR gateway.class.id = :class_id)', { class_id });
    }

    // 分页逻辑
    if (pageSize && pageNum) {
      query.skip((pageNum - 1) * pageSize).take(pageSize);
    }

    // 按时间降序排列
    query.orderBy('gateway.last_report_time', 'DESC'); // 建议用 last_report_time 排序更合理

    // 返回总数和数据
    return {
      total: await query.getCount(),
      data: await query.getMany(),
    };
  }

  // 获取所有网关_手环数量(gateway 表)
  async getAllGateways_Wb(queryParams) {
    console.log('queryParams', queryParams)
    const { mac, version, pageNum, pageSize } = queryParams
    let queryAll = this.gatewayRepo.createQueryBuilder('gateway');
    // 设置分页
    const skip = (pageNum - 1) * pageSize;  // 计算跳过的记录数
    const take = pageSize; // 设置每页返回的记录数
    // if (queryParams.last_report_time) {
    //   queryAll.andWhere('gateway.last_report_time = :last_report_time', { last_report_time: queryParams.last_report_time });
    // }
    if (mac) queryAll.andWhere('gateway.mac LIKE :mac', { mac: `%${mac}%` });
    if (version) queryAll.andWhere('gateway.version_bin LIKE :version', { version: `%${version}%` });
    // 降序排序
    queryAll.orderBy('gateway.time', 'DESC')
    // 添加分页到查询
    queryAll.skip(skip).take(take);
    let result = await queryAll.getMany() as any;


    // let query = "wristband_adv wba left join gateway g on g.mac=wba.gw_mac WHERE 1=1 "
    // if (mac) query += 'AND gw_mac = ?'
    // if (queryParams.date) query += 'AND wba.time = ?'
    // query += 'GROUP BY wba.time ORDER BY wba.time DESC LIMIT ? OFFSET ?'
    // // 动态构建参数
    // const params: any[] = [];
    // if (mac) {
    //   params.push(mac);
    // }
    // if (queryParams.date) {
    //   params.push(queryParams.date);
    // }
    // params.push(pageSize, (pageNum - 1) * pageSize); // 分页参数
    // // 执行查询
    // try {
    //   const wristbandCount = await this.gatewayRepo.query(query, params);
    //   console.log('Query result:', wristbandCount);
    //   // 将 wristbandCount 添加到 result 中
    //   result.forEach((item) => {
    //     const countItem = wristbandCount.find((count) => count.gw_mac === item.mac);
    //     if (countItem) {
    //       item.wb_cnt = countItem.count; // 添加手环数量到网关对象中
    //     } else {
    //       item.wb_cnt = 0; // 如果没有找到，设置为 0
    //     }
    //   });
    // } catch (error) {
    //   console.error('Error fetching wristband count:', error);
    //   throw error;
    // }

    return {
      total: await queryAll.getCount(), // 获取总记录数
      data: result,  // 返回总记录数
    };




    //   // queryParams.mac = queryParams.mac || '30:ed:a0:26:cd:0c'
    //   //  queryParams.date = queryParams.date || new Date()
    //   // 基础查询
    //   let query = `
    //     SELECT
    //       wba.gw_mac, 
    //       MAX(wba.time) AS last_adv_time,
    //       COUNT(wba.mac) AS count ,
    //       g.* -- @todo 改成需要的网关表的字段
    //     FROM
    //        wristband_adv wba left join gateway g on g.mac=wba.gw_mac
    //        WHERE 1=1
    //        ${queryParams.mac ? 'AND gw_mac = ?' : ''}
    //        ${queryParams.date ? 'AND wba.time = ?' : ''}
    //     GROUP BY wba.time
    //     ORDER BY wba.time DESC
    //     LIMIT ? OFFSET ?
    //   `;

    // //   let query = `
    // //   SELECT
    // //     wba.gw_mac, 
    // //     MAX(wba.time) AS last_adv_time,
    // //     COUNT(wba.mac) AS wb_cnt ,
    // //     g.* 
    // //   FROM wristband_adv wba left join gateway g on g.mac=wba.gw_mac
    // //      WHERE 1=1
    // //      ${queryParams.mac ? 'AND gw_mac = ?' : ''}
    // //      ${queryParams.date ? 'AND wba.time = ?' : ''}
    // // GROUP BY wba.time
    // // ORDER BY wba.time DESC
    // // limit 50
    // // `;

    //   // 动态构建参数
    //   const params: any[] = [];
    //   if (queryParams.mac) {
    //     params.push(queryParams.mac);
    //   }
    //   if (queryParams.date) {
    //     params.push(queryParams.date);
    //   }
    //   params.push(pageSize, (page - 1) * pageSize); // 分页参数

    //   try {
    //     const result = await this.gatewayRepo.query(query, params);
    //     console.log('Query result:', result);
    //     return result;
    //   } catch (error) {
    //     console.error('Error fetching wristband count:', error);
    //     throw error;
    //   }
  }



  // **根据 MAC 地址获取网关**
  async getGatewayByMac(mac: string) {
    const query = this.gatewayRepo.createQueryBuilder('gateway')
      .leftJoinAndSelect('gateway.class', 'class') // 关联 class
      .leftJoinAndSelect('class.school', 'school')
    if (mac) query.andWhere('gateway.mac = :mac', { mac });
    let result = await query.getMany()
    // console.log('query', result[0])
    return result[0];
  }


  // **根据 MAC 地址获取网关及手环**
  async getGatewayByMac_Wb(queryParams) {
    console.log(2222, queryParams)
    const query = this.wristbandAdvModel.createQueryBuilder('wristband_adv');
    let { date, time, wb_mac, gw_mac, pageNum, pageSize } = queryParams;

    // 设置分页
    const skip = (pageNum - 1) * pageSize;  // 计算跳过的记录数
    const take = pageSize; // 设置每页返回的记录数
    console.log(11111, date, gw_mac, wb_mac, pageNum, pageSize)
    if (wb_mac) {
      // 小写转大写 并启用模糊查询
      wb_mac = wb_mac.toUpperCase();
      query.andWhere('UPPER(wristband_adv.mac) LIKE UPPER(:mac)', { mac: `%${wb_mac}%` });
    }
    if (!gw_mac) throw new Error('网关地址不能为空')
    if (gw_mac) {
      query.andWhere('wristband_adv.gw_mac = :gw_mac', { gw_mac: gw_mac });
    }
    if (!time && !date) throw new Error('时间范围不能为空')
    // 如果传入时间范围，则使用传入的时间范围进行查询
    if (time && date) {
      throw new Error('时间范围只能传入一个！')
    }
    if (time) {
      // 查询gateway表中最后上报时间
      const lastReportTime = await this.gatewayRepo.createQueryBuilder('gateway')
        .select('MAX(gateway.last_report_time)', 'last_report_time')
        .where('gateway.mac = :gw_mac', { gw_mac })
        .getRawOne();
      console.log('lastReportTime', lastReportTime)
      if (!lastReportTime) throw new Error('网关不存在或没有上报时间！');
      // 计算最后上报时间的 time 毫秒范围内的时间
      // 1. 首先将字符串时间转换为 Date 对象
      const lastReportDate = new Date(lastReportTime.last_report_time);
      const fiveMinutesAgo = new Date(lastReportDate.getTime() - time);
      // 使用最后上报时间的 time 毫秒范围内的时间进行查询
      query.andWhere('wristband_adv.time >= :fiveMinutesAgo', { fiveMinutesAgo });
      // 如果需要查看结果
      console.log(time, '毫秒前', fiveMinutesAgo); // 输出: 2025-04-28T19:32:14.000Z
    }
    // 如果传入了时间范围，则使用传入的时间范围进行查询
    if (date) {
      query.andWhere('wristband_adv.time BETWEEN :start AND :end', {
        start: `${date[0]}`,
        end: `${date[1]}`,
      });
    }

    query.orderBy('wristband_adv.time', 'DESC');
    // 添加分页到查询
    query.skip(skip).take(take);
    let result = await query.getMany() as any;
    // 计算睡眠数据
    const sleepStats = calculateSleepData(result);

    result.forEach((item) => {
      // 赋值计算出的睡眠数据
      item.sleep_duration = sleepStats.sleep_duration;
      item.wake_up_time = sleepStats.wake_up_time;
      item.bed_time = sleepStats.bed_time;
      item.deep_sleep_duration = sleepStats.deep_sleep_duration;
      item.light_sleep_duration = sleepStats.light_sleep_duration;
    });

    // 返回分页后的结果
    const total = await query.getCount(); // 获取总记录数
    return {
      data: result,
      total,  // 返回总记录数
      pageNum,  // 当前页码
      pageSize,  // 每页条数
    };
  }


  // **更新网关信息并清理 Redis 缓存**
  async updateGateway(mac: string, updateData: Partial<Gateway>) {
    // 1. 获取原始网关数据
    const gateway = await this.getGatewayByMac(mac);
    if (!gateway) throw new Error(`网关不存在！`);
    // 2. 检查 topic 是否有变化
    const isTopicChanged = 'topic' in updateData && updateData.topic !== gateway.topic;
    // 3. 直接更新数据库，不需要先修改本地对象
    try {
      let updateDataVal = updateData as any;
      delete updateDataVal.version;
      const updatedGateway = await this.gatewayRepo.update(mac, updateData);
      // 4. 仅当 topic 变化时清理缓存
      if (isTopicChanged) {
        const redisKey = `gateway:${mac}`;
        await this.redisService.del(redisKey);
        console.log(`检测到 topic 变更，已清理 Redis 缓存: ${mac}`);
      }
      return updatedGateway;
    } catch (err) {
      console.error('更新网关失败:', err);
      throw err; // 最好重新抛出错误，让调用者知道操作失败
    }
  }


  // 分配网关到班级
  async setGwClass(body: { class_id: number; macList: string[] }) {
    const classEntity = await this.classRepo.findOne({
      where: { id: body.class_id }
    });
    if (!classEntity) {
      throw new Error(`Class with id ${body.class_id} not found`);
    }

    try {
      // 1. 先移除该班级之前关联的所有网关
      await this.gatewayRepo
        .createQueryBuilder()
        .update()
        .set({ class: null }) // 或者使用 classId: null 取决于你的实体定义
        .where("class.id = :classId", { classId: body.class_id })
        .execute();
    } catch (err) {
      console.log('err1', err)
    }


    // 2. 使用Promise.all并行处理所有网关
    await Promise.all(body.macList.map(async (mac) => {
      // 添加 trim 防止空格
      const gateway = await this.gatewayRepo.findOneBy({ mac: mac.trim() });

      if (!gateway) {
        throw new Error(`Gateway with mac ${mac} not found`);
      }

      // 3. 更新关联
      gateway.class = classEntity;
      await this.gatewayRepo.save(gateway);
    }));
  }


  // 删除网关并清理 Redis 缓存
  async deleteGateway(mac: string) {
    // 1. 删除数据库记录
    const result = await this.gatewayRepo.delete({ mac });
    // 2. 如果数据库删除成功，清理 Redis 缓存
    if (result.affected > 0) {
      await this.redisService.del(`gateway:${mac}`);
      console.log(`网关 ${mac} 已删除，Redis 缓存已清理`);
    }
    return result.affected > 0;
  }
}
